package tk.mystudio.ocr;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.imageio.ImageIO;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class OCR {
	protected transient final static Logger logger = LoggerFactory.getLogger("OCR");
	private final static String LANG_OPTION = "-l";
	private final static String IMAGE_EXT = "tif";
	private final static String EOL = System.getProperty("line.separator");
	private static String tessPath = new File("tesseract").getAbsolutePath();

	public static String read(byte[] image) {
		File file = new File("tesseract", System.currentTimeMillis() + ".png");
		String randCode = "";
		try {
			DataOutputStream dos = new DataOutputStream(new FileOutputStream(file));
			dos.write(image);
			dos.flush();
			dos.close();
			randCode = read(file);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			//file.delete();
		}
		randCode = randCode.replaceAll("\\s", "");
		return randCode;
	}

	private static String read(File imageFile) throws Exception {
		String result = "";
		BufferedImage buffImg = ImageIO.read(imageFile);
		if (buffImg == null) {
			return result;
		}
		greyImage(buffImg);
		twoValueImage(buffImg);
		BufferedImage newcleanbuffImg = createEmptyImage(buffImg, buffImg.getWidth() * 2, buffImg.getHeight());
		splitAndCleanImgToNew(buffImg, newcleanbuffImg);
        BufferedImage newcenterbuffImg = createEmptyImage(buffImg, buffImg.getWidth() * 2, buffImg.getHeight());
        combineAndCenterBuffImgsToNew(splitbuffImgs(newcleanbuffImg), newcenterbuffImg);

		boolean status = ImageIO.write(newcenterbuffImg, IMAGE_EXT, new File(imageFile.getParentFile(), imageFile.getName() + "." + IMAGE_EXT));

		File outputFile = new File(imageFile.getParentFile(), "output");
		StringBuffer strB = new StringBuffer();

		List<String> cmd = new ArrayList<String>();
		cmd.add(tessPath + "\\tesseract");
		cmd.add("");
		cmd.add(outputFile.getName());
        cmd.add(LANG_OPTION);
        cmd.add("eng");
        cmd.add("digitsandalphabets");

		ProcessBuilder pb = new ProcessBuilder(new String[0]);
		pb.directory(imageFile.getParentFile());
		if (status)
			cmd.set(1, imageFile.getName() + "." + IMAGE_EXT);
		else
			cmd.set(1, imageFile.getName());
		pb.command(cmd);
		pb.redirectErrorStream(true);
		Process process = pb.start();
		int w = process.waitFor();
		if (w == 0) {
			BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(outputFile.getAbsolutePath() + ".txt"), "UTF-8"));
			String str;
			while ((str = in.readLine()) != null) {
				strB.append(str).append(EOL);
			}
			in.close();
		} else {
			String msg;
			switch (w) {
			case 1:
				msg = "Errors accessing files. There may be spaces in your image's filename.";
				break;
			case 29:
				msg = "Cannot recognize the image or its selected region.";
				break;
			case 31:
				msg = "Unsupported image format.";
				break;
			default:
				msg = "Errors occurred.";
			}
			throw new RuntimeException(msg);
		}
		new File(outputFile.getAbsolutePath() + ".txt").delete();
		new File(imageFile.getAbsolutePath() + "." + IMAGE_EXT).delete();
		result = strB.toString().trim();
		return result;
	}

    /**
     * 将所有分好层的图层拷贝到新图层，居中显示
     * @param buffImg 现有图层
     * @param newbuffImg 新图层
     * @return
     */
    private static void combineAndCenterBuffImgsToNew(List<Map<Boundary, BufferedImage>> buffImgs, BufferedImage newbuffImg) {
        int lastnewX = 0;
        for (Iterator<Map<Boundary, BufferedImage>> iter = buffImgs.iterator(); iter.hasNext();) {
            Map<Boundary, BufferedImage> buffImgMap = iter.next();
            Boundary bound = buffImgMap.keySet().iterator().next();
            BufferedImage tempbuffImg = buffImgMap.get(bound);
            lastnewX = copyTempImgToNewbuffImg(tempbuffImg, newbuffImg, bound, lastnewX);
        }
    }
    
    /**
     * 将现有图层分层
     * @param buffImg 现有图层
     * @param newbuffImg 新图层
     * @return
     */
    private static List<Map<Boundary, BufferedImage>> splitbuffImgs(BufferedImage buffImg) {
        List<Map<Boundary, BufferedImage>> returnbuffImgs = new ArrayList<Map<Boundary, BufferedImage>>();
        List<Map<Boundary, BufferedImage>> buffImgs = new ArrayList<Map<Boundary, BufferedImage>>();
        int height = buffImg.getHeight();
        int width = buffImg.getWidth();
        int minY = 0;
        int minX = 0;
        boolean flag = true;
        Map<Integer, Map<String, Object>> cacheStrangeContinueTempBuffImgMap = new LinkedHashMap<Integer, Map<String, Object>>();
        int i = 0;
        while (flag) {
            Boundary bound = new Boundary();
            BufferedImage tempbuffImg = createEmptyImage(buffImg, buffImg.getWidth(), buffImg.getHeight());
            for (int x = minX; x < width; x++) {
                if (bound.minX != -1) {
                    break;
                }
                for (int y = minY; y < height; y++) {
                    int rgb = buffImg.getRGB(x, y);
                    Color color = new Color(rgb); // 根据rgb的int值分别取得r,g,b颜色。
                    if (color.getRed() < 180 || color.getGreen() < 180 || color.getBlue() < 180) {
                        bound.minX = bound.maxX = x;
                        bound.minY = bound.maxY = y;
                        break;
                    }
                }
            }
            if (bound.minX == -1) {
                flag = false;
            } else {
                cutContinuousCleanPointToTempImg(bound.minX, bound.minY, buffImg, tempbuffImg, bound);
                Map<String, Object> itemmap = new HashMap<String, Object>();
                itemmap.put("bound", bound);
                itemmap.put("tempbuffImg", tempbuffImg);
                cacheStrangeContinueTempBuffImgMap.put(i++, itemmap);
            }
        }
        Entry<Integer, Map<String, Object>> lastEntry = null;
        for (Iterator<Entry<Integer, Map<String, Object>>> iter = cacheStrangeContinueTempBuffImgMap.entrySet().iterator(); iter.hasNext();) {
            Entry<Integer, Map<String, Object>> entry = iter.next();
            BufferedImage tempbuffImg = (BufferedImage) entry.getValue().get("tempbuffImg");
            Boundary bound = (Boundary) entry.getValue().get("bound");
            boolean isrelateToNext = false;
            if (iter.hasNext()) {
                isrelateToNext = true;
            }
            boolean isrelateToLast = false;
            if (lastEntry != null) {
                BufferedImage lastTempbuffImg = (BufferedImage) lastEntry.getValue().get("tempbuffImg");
                Boundary lastBound = (Boundary) lastEntry.getValue().get("bound");
                int vdistance = calTwoBuffImgDistance(lastTempbuffImg, tempbuffImg, 1);
                int ldistance = calTwoBuffImgDistance(lastTempbuffImg, tempbuffImg, 2);
                if (vdistance < 4 || ldistance < 2) {
                    isrelateToLast = true;
                }
                if (isrelateToLast) {
                    copyTempImgToNewbuffImg(lastTempbuffImg, tempbuffImg);
                    bound.maxX = (bound.maxX > lastBound.maxX) ? bound.maxX : lastBound.maxX;
                    bound.maxY = (bound.maxY > lastBound.maxY) ? bound.maxY : lastBound.maxY;
                    bound.minX = (bound.minX < lastBound.minX) ? bound.minX : lastBound.minX;
                    bound.minY = (bound.minY < lastBound.minY) ? bound.minY : lastBound.minY;
                } else {
                    Map<Boundary, BufferedImage> buffImgMap = new LinkedHashMap<Boundary, BufferedImage>();
                    buffImgMap.put(lastBound, lastTempbuffImg);
                    buffImgs.add(buffImgMap);
                }
            }
            if (!isrelateToNext) {
                Map<Boundary, BufferedImage> buffImgMap = new LinkedHashMap<Boundary, BufferedImage>();
                buffImgMap.put(bound, tempbuffImg);
                buffImgs.add(buffImgMap);
                lastEntry = null;
            } else {
                lastEntry = entry;
            }
        }
        int buffSize = buffImgs.size();
        if (buffSize < 4) {//小于四个图层时,格式化为四个图层
            int actualWidth = 0;//字符实际所占宽
            for (Map<Boundary, BufferedImage> buffImgMap : buffImgs) {
                if (buffImgMap.size() > 0) {
                    actualWidth += buffImgMap.keySet().iterator().next().getWidth();
                }
            }
            if(buffSize == 1) {
                Map<Boundary, BufferedImage> buffImgMap0 = buffImgs.get(0);
                Boundary bound0 = buffImgMap0.keySet().iterator().next();
                BufferedImage buffImg0 = buffImgMap0.get(bound0);
                int num0 = 4;
                List<Map<Boundary, BufferedImage>> itemBuffImgs0 = splitBuffImgByMinHeight(buffImg0, bound0, actualWidth, num0);
                for(Map<Boundary, BufferedImage> buffImgMap : itemBuffImgs0) {
                    returnbuffImgs.add(buffImgMap);
                }
                
            } else if(buffSize == 2) {
                Map<Boundary, BufferedImage> buffImgMap0 = buffImgs.get(0);
                Boundary bound0 = buffImgMap0.keySet().iterator().next();
                BufferedImage buffImg0 = buffImgMap0.get(bound0);
                int num0 = (int) ((bound0.getWidth() * 4.0 / actualWidth) + 0.125);
                List<Map<Boundary, BufferedImage>> itemBuffImgs0 = splitBuffImgByMinHeight(buffImg0, bound0, actualWidth, num0);
                for(Map<Boundary, BufferedImage> buffImgMap : itemBuffImgs0) {
                    returnbuffImgs.add(buffImgMap);
                }
                
                Map<Boundary, BufferedImage> buffImgMap1 = buffImgs.get(1);
                Boundary bound1 = buffImgMap1.keySet().iterator().next();
                BufferedImage buffImg1 = buffImgMap1.get(bound1);
                int num1 = 4 - num0;
                List<Map<Boundary, BufferedImage>> itemBuffImgs1 = splitBuffImgByMinHeight(buffImg1, bound1, actualWidth, num1);
                for(Map<Boundary, BufferedImage> buffImgMap : itemBuffImgs1) {
                    returnbuffImgs.add(buffImgMap);
                }
                
            } else if(buffSize == 3) {
                Map<Boundary, BufferedImage> buffImgMap0 = buffImgs.get(0);
                Boundary bound0 = buffImgMap0.keySet().iterator().next();
                BufferedImage buffImg0 = buffImgMap0.get(bound0);
                int num0 = (int) ((bound0.getWidth() * 4.0 / actualWidth) + 0.125);
                List<Map<Boundary, BufferedImage>> itemBuffImgs0 = splitBuffImgByMinHeight(buffImg0, bound0, actualWidth, num0);
                for(Map<Boundary, BufferedImage> buffImgMap : itemBuffImgs0) {
                    returnbuffImgs.add(buffImgMap);
                }
                
                Map<Boundary, BufferedImage> buffImgMap1 = buffImgs.get(1);
                Boundary bound1 = buffImgMap1.keySet().iterator().next();
                BufferedImage buffImg1 = buffImgMap1.get(bound1);
                int num1 = (int) ((bound1.getWidth() * 4.0 / actualWidth) + 0.125);
                List<Map<Boundary, BufferedImage>> itemBuffImgs1 = splitBuffImgByMinHeight(buffImg1, bound1, actualWidth, num1);
                for(Map<Boundary, BufferedImage> buffImgMap : itemBuffImgs1) {
                    returnbuffImgs.add(buffImgMap);
                }
                
                Map<Boundary, BufferedImage> buffImgMap2 = buffImgs.get(2);
                Boundary bound2 = buffImgMap2.keySet().iterator().next();
                BufferedImage buffImg2 = buffImgMap2.get(bound2);
                int num2 = 4  - num0 - num1;
                List<Map<Boundary, BufferedImage>> itemBuffImgs2 = splitBuffImgByMinHeight(buffImg2, bound2, actualWidth, num2);
                for(Map<Boundary, BufferedImage> buffImgMap : itemBuffImgs2) {
                    returnbuffImgs.add(buffImgMap);
                }
                
            }
        } else {
            for(Map<Boundary, BufferedImage> buffImgMap : buffImgs) {
                returnbuffImgs.add(buffImgMap);
            }
        }
        return returnbuffImgs;
    }
    
    /**
     * 将缓存图根据实际宽找出最小垂直系数划分成num份缓存图
     * @param buffImgMap
     * @param width
     * @param num
     * @return
     */
    private static List<Map<Boundary, BufferedImage>> splitBuffImgByMinHeight(BufferedImage buffImg, Boundary bound, int width, int num) {
        List<Map<Boundary, BufferedImage>> returnbuffImgs = new ArrayList<Map<Boundary, BufferedImage>>();
        if(num == 4) {
            int start0 = bound.minX + bound.getWidth() / 8 + 2;
            int end0 = start0 + bound.getWidth() / 4 - 2;
            int xIndex0 = findXByMinHeight(buffImg, bound, start0, end0);
            Boundary bound0 = new Boundary();
            bound0.minX = bound.minX;
            bound0.maxX = xIndex0 - 1;
            bound0.minY = bound.minY;
            bound0.maxY = bound.maxY;
            BufferedImage buffImg0 = cutBuffImgByXrange(buffImg, bound0);
            Map<Boundary, BufferedImage> buffImgMap0 = new LinkedHashMap<Boundary, BufferedImage>();
            buffImgMap0.put(bound0, buffImg0);
            returnbuffImgs.add(buffImgMap0);
            
            int start1 = end0 + 2;
            int end1 = start1 + bound.getWidth() / 4 - 2;
            int xIndex1 = findXByMinHeight(buffImg, bound, start1, end1);
            Boundary bound1 = new Boundary();
            bound1.minX = xIndex0 + 1;
            bound1.maxX = xIndex1 - 1;
            bound1.minY = bound.minY;
            bound1.maxY = bound.maxY;
            BufferedImage buffImg1 = cutBuffImgByXrange(buffImg, bound1);
            Map<Boundary, BufferedImage> buffImgMap1 = new LinkedHashMap<Boundary, BufferedImage>();
            buffImgMap1.put(bound1, buffImg1);
            returnbuffImgs.add(buffImgMap1);
            
            int start2 = end1 + 2;
            int end2 = start2 + bound.getWidth() / 4 - 2;
            int xIndex2 = findXByMinHeight(buffImg, bound, start2, end2);
            Boundary bound2 = new Boundary();
            bound2.minX = xIndex1 + 1;
            bound2.maxX = xIndex2 - 1;
            bound2.minY = bound.minY;
            bound2.maxY = bound.maxY;
            BufferedImage buffImg2 = cutBuffImgByXrange(buffImg, bound2);
            Map<Boundary, BufferedImage> buffImgMap2 = new LinkedHashMap<Boundary, BufferedImage>();
            buffImgMap2.put(bound2, buffImg2);
            returnbuffImgs.add(buffImgMap2);
            
            Boundary bound3 = new Boundary();
            bound3.minX = xIndex2 + 1;
            bound3.maxX = bound.maxX;
            bound3.minY = bound.minY;
            bound3.maxY = bound.maxY;
            BufferedImage buffImg3 = cutBuffImgByXrange(buffImg, bound3);
            Map<Boundary, BufferedImage> buffImgMap3 = new LinkedHashMap<Boundary, BufferedImage>();
            buffImgMap3.put(bound3, buffImg3);
            returnbuffImgs.add(buffImgMap3);
            
        } else if(num == 3) {
            int start0 = bound.minX + bound.getWidth() / 6 + 2;
            int end0 = start0 + bound.getWidth() / 3 - 2;
            int xIndex0 = findXByMinHeight(buffImg, bound, start0, end0);
            Boundary bound0 = new Boundary();
            bound0.minX = bound.minX;
            bound0.maxX = xIndex0 - 1;
            bound0.minY = bound.minY;
            bound0.maxY = bound.maxY;
            BufferedImage buffImg0 = cutBuffImgByXrange(buffImg, bound0);
            Map<Boundary, BufferedImage> buffImgMap0 = new LinkedHashMap<Boundary, BufferedImage>();
            buffImgMap0.put(bound0, buffImg0);
            returnbuffImgs.add(buffImgMap0);
            
            int start1 = end0 + 2;
            int end1 = start1 + bound.getWidth() / 3 - 2;
            int xIndex1 = findXByMinHeight(buffImg, bound, start1, end1);
            Boundary bound1 = new Boundary();
            bound1.minX = xIndex0 + 1;
            bound1.maxX = xIndex1 - 1;
            bound1.minY = bound.minY;
            bound1.maxY = bound.maxY;
            BufferedImage buffImg1 = cutBuffImgByXrange(buffImg, bound1);
            Map<Boundary, BufferedImage> buffImgMap1 = new LinkedHashMap<Boundary, BufferedImage>();
            buffImgMap1.put(bound1, buffImg1);
            returnbuffImgs.add(buffImgMap1);
            
            Boundary bound2 = new Boundary();
            bound2.minX = xIndex1 + 1;
            bound2.maxX = bound.maxX;
            bound2.minY = bound.minY;
            bound2.maxY = bound.maxY;
            BufferedImage buffImg2 = cutBuffImgByXrange(buffImg, bound2);
            Map<Boundary, BufferedImage> buffImgMap2 = new LinkedHashMap<Boundary, BufferedImage>();
            buffImgMap2.put(bound2, buffImg2);
            returnbuffImgs.add(buffImgMap2);
            
        } else if (num == 2) {
            int start0 = bound.minX + bound.getWidth() / 4 + 2;
            int end0 = bound.maxX - bound.getWidth() / 4 - 2;
            int xIndex0 = findXByMinHeight(buffImg, bound, start0, end0);
            Boundary bound0 = new Boundary();
            bound0.minX = bound.minX;
            bound0.maxX = xIndex0 - 1;
            bound0.minY = bound.minY;
            bound0.maxY = bound.maxY;
            BufferedImage buffImg0 = cutBuffImgByXrange(buffImg, bound0);
            Map<Boundary, BufferedImage> buffImgMap0 = new LinkedHashMap<Boundary, BufferedImage>();
            buffImgMap0.put(bound0, buffImg0);
            returnbuffImgs.add(buffImgMap0);
            
            Boundary bound1 = new Boundary();
            bound1.minX = xIndex0 + 1;
            bound1.maxX = bound.maxX;
            bound1.minY = bound.minY;
            bound1.maxY = bound.maxY;
            BufferedImage buffImg1 = cutBuffImgByXrange(buffImg, bound1);
            Map<Boundary, BufferedImage> buffImgMap1 = new LinkedHashMap<Boundary, BufferedImage>();
            buffImgMap1.put(bound1, buffImg1);
            returnbuffImgs.add(buffImgMap1);
        } else {
            Map<Boundary, BufferedImage> buffImgMap0 = new LinkedHashMap<Boundary, BufferedImage>();
            buffImgMap0.put(bound, buffImg);
            returnbuffImgs.add(buffImgMap0);
        }
        return returnbuffImgs;
    }
    
    private static BufferedImage cutBuffImgByXrange(BufferedImage buffImg, Boundary bound) {
        BufferedImage tempbuffImg = createEmptyImage(buffImg, buffImg.getWidth(), buffImg.getHeight());
        for (int x = bound.minX; x <= bound.maxX; x++) {
            for (int y = bound.minY; y <= bound.maxY; y++) {
                tempbuffImg.setRGB(x, y, buffImg.getRGB(x, y));
            }
        }
        return tempbuffImg;
    }

    /**
     * 找出缓存图中对应横坐标范围内最小垂直系数
     * @param buffImg
     * @param bound
     * @param start
     * @param end
     * @return
     */
    private static int findXByMinHeight(BufferedImage buffImg, Boundary bound, int start, int end) {
        int xIndex = bound.minX + bound.getWidth()/2;
        int minYDistance = 10;
        for(int x = start; x < end; x++) {
            int minY = 0;
            int maxY = buffImg.getHeight(null);
            for(int y1 = 0; y1 < buffImg.getHeight(null); y1++) {
                int rgb = buffImg.getRGB(x, y1);
                Color color = new Color(rgb);
                if (color.getRed() < 180 || color.getGreen() < 180 || color.getBlue() < 180) {
                    minY = y1;
                    break;
                }
            }
            for(int y2 = buffImg.getHeight(null) - 1; y2 >= 0; y2--) {
                int rgb = buffImg.getRGB(x, y2);
                Color color = new Color(rgb);
                if (color.getRed() < 180 || color.getGreen() < 180 || color.getBlue() < 180) {
                    maxY = y2;
                    break;
                }
            }
            if(maxY - minY < minYDistance) {
                minYDistance = maxY - minY;
                xIndex = x;
            }
        }
        return xIndex;
    }

	private static int copyTempImgToNewbuffImg(BufferedImage tempbuffImg, BufferedImage newbuffImg, Boundary bound, int lastnewX) {
		int newheight = newbuffImg.getHeight();
		Boundary newbound = new Boundary();
		newbound.minX = lastnewX + 3;
		newbound.minY = 0;
		newbound.maxX = newbound.minX + bound.getWidth() + 3;
		int initnewx = newbound.minX;
		int initnewy = (newheight - bound.maxY + bound.minY) / 2;
		int inittempx = bound.minX;
		int inittempy = bound.minY;
		for (int y = 0; y < bound.getHeight(); y++) {
			for (int x = 0; x < bound.getWidth(); x++) {
				int rgb = tempbuffImg.getRGB(inittempx + x, inittempy + y);
				Color color = new Color(rgb); // 根据rgb的int值分别取得r,g,b颜色。
				if (color.getRed() < 180 || color.getGreen() < 180 || color.getBlue() < 180) {
					newbuffImg.setRGB(initnewx + x, initnewy + y, rgb);
				}
			}
		}
		return newbound.maxX;
	}

	/**
	 * 将现有图层拷贝到新图层，并且将不连续的点图分离开来，然后去掉小黑点
	 * 
	 * @param buffImg
	 *            现有图层
	 * @param newbuffImg
	 *            新图层
	 * @return
	 */
	private static void splitAndCleanImgToNew(BufferedImage buffImg, BufferedImage newbuffImg) {
		int height = buffImg.getHeight();
		int width = buffImg.getWidth();
		int minY = 0;
		int minX = 0;
		boolean flag = true;
		while (flag) {
			Boundary bound = new Boundary();
			BufferedImage tempbuffImg = createEmptyImage(buffImg, buffImg.getWidth(), buffImg.getHeight());
			for (int x = minX; x < width; x++) {
				if (bound.minX != -1) {
					break;
				}
				for (int y = minY; y < height; y++) {
					int rgb = buffImg.getRGB(x, y);
					Color color = new Color(rgb); // 根据rgb的int值分别取得r,g,b颜色。
					if (color.getRed() < 180 || color.getGreen() < 180 || color.getBlue() < 180) {
						bound.minX = bound.maxX = x;
						bound.minY = bound.maxY = y;
						break;
					}
				}
			}
			if (bound.minX == -1) {
				flag = false;
			} else {
				cutContinuousCleanPointToTempImg(bound.minX, bound.minY, buffImg, tempbuffImg, bound);
				if (bound.getWidth() > 4 || bound.getHeight() > 4) {
					copyTempImgToNewbuffImg(tempbuffImg, newbuffImg);
				}
			}
		}
	}

	private static void copyTempImgToNewbuffImg(BufferedImage tempbuffImg, BufferedImage newbuffImg) {
		int height = tempbuffImg.getHeight();
		int width = tempbuffImg.getWidth();
		int minY = 0;
		int minX = 0;
		for (int y = minY; y < height; y++) {
			for (int x = minX; x < width; x++) {
				int rgb = tempbuffImg.getRGB(x, y);
				Color color = new Color(rgb); // 根据rgb的int值分别取得r,g,b颜色。
				if (color.getRed() < 180 || color.getGreen() < 180 || color.getBlue() < 180) {
					newbuffImg.setRGB(x, y, rgb);
				}
			}
		}
	}

	/**
	 * 计算两张图片的距离
	 * 
	 * @param buffImg1
	 * @param buffImg2
	 * @param type
	 *            类型 实际距离:0;垂直距离:1;水平距离:2;
	 * @return
	 */
	private static int calTwoBuffImgDistance(BufferedImage buffImg1, BufferedImage buffImg2, int type) {
		int height1 = buffImg1.getHeight();
		int width1 = buffImg1.getWidth();
		int height2 = buffImg2.getHeight();
		int width2 = buffImg2.getWidth();
		int minY = 0;
		int minX = 0;
		int length = 100;
		for (int y1 = minY; y1 < height1; y1++) {
			for (int x1 = minX; x1 < width1; x1++) {
				int rgb1 = buffImg1.getRGB(x1, y1);
				Color color1 = new Color(rgb1); // 根据rgb的int值分别取得r,g,b颜色。
				if (color1.getRed() < 180 || color1.getGreen() < 180 || color1.getBlue() < 180) {
					for (int y2 = minY; y2 < height2; y2++) {
						for (int x2 = minX; x2 < width2; x2++) {
							int rgb2 = buffImg2.getRGB(x2, y2);
							Color color2 = new Color(rgb2); // 根据rgb的int值分别取得r,g,b颜色。
							if (color2.getRed() < 180 || color2.getGreen() < 180 || color2.getBlue() < 180) {
								int tempminlen = 100;
								if (type == 0) {
									if (x1 == x2) {
										tempminlen = Math.abs(y2 - y1);
									}
									if (y1 == y2) {
										tempminlen = Math.abs(x2 - x1);
									}
									if (tempminlen == 100) {
										tempminlen = (int) Math.sqrt((y2 - y1) * (y2 - y1) + (x2 - x1) * (x2 - x1));
									}
								} else if (type == 1) {
									if (x1 == x2) {
										tempminlen = Math.abs(y2 - y1);
									}
								} else if (type == 2) {
									if (y1 == y2) {
										tempminlen = Math.abs(x2 - x1);
									}
								}
								if (tempminlen < length) {
									length = tempminlen;
								}
							}
						}
					}
				}
			}
		}
		return length;
	}

	/**
	 * 剪切连续点到临时图层
	 * 
	 * @param x
	 * @param y
	 * @param buffImg
	 * @param tempbuffImg
	 * @param bound
	 */
	private static void cutContinuousCleanPointToTempImg(int x, int y, BufferedImage buffImg, BufferedImage tempbuffImg, Boundary bound) {
		int height = buffImg.getHeight();
		int width = buffImg.getWidth();
		int minY = 0;
		int minX = 0;
		buffImg.setRGB(x, y, Color.WHITE.getRGB());
		tempbuffImg.setRGB(x, y, Color.BLACK.getRGB());
		if (x < bound.minX) {
			bound.minX = x;
		}
		if (y < bound.minY) {
			bound.minY = y;
		}
		if (x > bound.maxX) {
			bound.maxX = x;
		}
		if (y > bound.maxY) {
			bound.maxY = y;
		}
		// 直
		if (y > minY) {
			int rgbt = buffImg.getRGB(x, y - 1);
			Color color = new Color(rgbt); // 根据rgb的int值分别取得r,g,b颜色。
			if (color.getRed() < 180 || color.getGreen() < 180 || color.getBlue() < 180) {
				cutContinuousCleanPointToTempImg(x, y - 1, buffImg, tempbuffImg, bound);
			}
		}
		if (x > minX) {
			int rgbt = buffImg.getRGB(x - 1, y);
			Color color = new Color(rgbt); // 根据rgb的int值分别取得r,g,b颜色。
			if (color.getRed() < 180 || color.getGreen() < 180 || color.getBlue() < 180) {
				cutContinuousCleanPointToTempImg(x - 1, y, buffImg, tempbuffImg, bound);
			}
		}
		if (y < height - 1) {
			int rgbt = buffImg.getRGB(x, y + 1);
			Color color = new Color(rgbt); // 根据rgb的int值分别取得r,g,b颜色。
			if (color.getRed() < 180 || color.getGreen() < 180 || color.getBlue() < 180) {
				cutContinuousCleanPointToTempImg(x, y + 1, buffImg, tempbuffImg, bound);
			}
		}
		if (x < width - 1) {
			int rgbt = buffImg.getRGB(x + 1, y);
			Color color = new Color(rgbt); // 根据rgb的int值分别取得r,g,b颜色。
			if (color.getRed() < 180 || color.getGreen() < 180 || color.getBlue() < 180) {
				cutContinuousCleanPointToTempImg(x + 1, y, buffImg, tempbuffImg, bound);
			}
		}
		// 斜
		if (x > minX && y > minY) {
			int rgbt = buffImg.getRGB(x - 1, y - 1);
			Color color = new Color(rgbt); // 根据rgb的int值分别取得r,g,b颜色。
			if (color.getRed() < 180 || color.getGreen() < 180 || color.getBlue() < 180) {
				cutContinuousCleanPointToTempImg(x - 1, y - 1, buffImg, tempbuffImg, bound);
			}
		}
		if (x > minX && y < height - 1) {
			int rgbt = buffImg.getRGB(x - 1, y + 1);
			Color color = new Color(rgbt); // 根据rgb的int值分别取得r,g,b颜色。
			if (color.getRed() < 180 || color.getGreen() < 180 || color.getBlue() < 180) {
				cutContinuousCleanPointToTempImg(x - 1, y + 1, buffImg, tempbuffImg, bound);
			}
		}
		if (x < width - 1 && y < height - 1) {
			int rgbt = buffImg.getRGB(x + 1, y + 1);
			Color color = new Color(rgbt); // 根据rgb的int值分别取得r,g,b颜色。
			if (color.getRed() < 180 || color.getGreen() < 180 || color.getBlue() < 180) {
				cutContinuousCleanPointToTempImg(x + 1, y + 1, buffImg, tempbuffImg, bound);
			}
		}
		if (x < width - 1 && y > minY) {
			int rgbt = buffImg.getRGB(x + 1, y - 1);
			Color color = new Color(rgbt); // 根据rgb的int值分别取得r,g,b颜色。
			if (color.getRed() < 180 || color.getGreen() < 180 || color.getBlue() < 180) {
				cutContinuousCleanPointToTempImg(x + 1, y - 1, buffImg, tempbuffImg, bound);
			}
		}
	}

	/**
	 * 创建一个空白图片
	 * 
	 * @param targetW
	 *            目标长
	 * @param targetH
	 *            目标宽
	 * @return
	 */
	private static BufferedImage createEmptyImage(BufferedImage source, int targetW, int targetH) {
		BufferedImage target = null;
		int imageType = source.getType();
		if (imageType == BufferedImage.TYPE_CUSTOM) { // handmade
			ColorModel cm = source.getColorModel();
			WritableRaster raster = cm.createCompatibleWritableRaster(targetW, targetH);
			boolean alphaPremultiplied = cm.isAlphaPremultiplied();
			target = new BufferedImage(cm, raster, alphaPremultiplied, null);
		} else {
			target = new BufferedImage(targetW, targetH, imageType);
		}
		int height = target.getHeight();
		int width = target.getWidth();
		int minY = 0;
		int minX = 0;
		for (int y = minY; y < height; y++) {
			for (int x = minX; x < width; x++) {
				target.setRGB(x, y, Color.WHITE.getRGB());
			}
		}
		return target;
	}

	/**
	 * 1.灰度化图片
	 * 
	 * @return
	 */
	private static void greyImage(BufferedImage buffImg) {
		// 1.首先灰度化，灰度值=0.3R+0.59G+0.11B：
		int height = buffImg.getHeight();
		int width = buffImg.getWidth();
		int minY = 0;
		int minX = 0;
		for (int y = minY; y < height; y++) {
			for (int x = minX; x < width; x++) {
				int rgb = buffImg.getRGB(x, y);
				Color color = new Color(rgb); // 根据rgb的int值分别取得r,g,b颜色。
				// int gray = (int) (0.3 * color.getRed() + 0.59 *
				// color.getGreen() + 0.11 * color.getBlue());
				int gray = (int) (0.25 * color.getRed() + 0.65 * color.getGreen() + 0.1 * color.getBlue());
				Color newColor = new Color(gray, gray, gray);
				buffImg.setRGB(x, y, newColor.getRGB());
			}
		}
	}

	/**
	 * 2.二值化图片
	 * 
	 * @return
	 */
	private static void twoValueImage(BufferedImage buffImg) {
		// 3.再次是二值化，取图片的平均灰度作为阈值，低于该值的全都为0，高于该值的全都为255：
		int height = buffImg.getHeight();
		int width = buffImg.getWidth();
		int minY = 0;
		int minX = 0;
		for (int y = minY; y < height; y++) {
			for (int x = minX; x < width; x++) {
				int rgb = buffImg.getRGB(x, y);
				Color color = new Color(rgb); // 根据rgb的int值分别取得r,g,b颜色。
				if (color.getRed() < 180 || color.getGreen() < 180 || color.getBlue() < 180) {
					buffImg.setRGB(x, y, Color.BLACK.getRGB());
				} else {
					buffImg.setRGB(x, y, Color.WHITE.getRGB());
				}
			}
		}
	}

	private static class Boundary {
		int minX = -1;
		int minY = -1;
		int maxX = -1;
		int maxY = -1;

		int getWidth() {
			return maxX - minX + 1;
		}

		int getHeight() {
			return maxY - minY + 1;
		}
	}

}
